package com.zt.csp.shorturl.service.impl;

import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.ecfront.dew.common.$;
import com.zt.csp.shorturl.constents.RedisKey;
import com.zt.csp.shorturl.dto.ServiceResult;
import com.zt.csp.shorturl.dto.ShortUrlDTO;
import com.zt.csp.shorturl.entity.ShortUrl;
import com.zt.csp.shorturl.mapper.ShortUrlMapper;
import com.zt.csp.shorturl.service.ShortUrlService;
import com.zt.csp.shorturl.utils.ConvertRadix;
import com.zt.csp.shorturl.utils.ThreadLocalUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 短链接服务实现
 * Created by zt on 2018/4/11 0011
 */
@Service
public class ShortUrlServiceImpl implements ShortUrlService {
    private static final Logger logger = LoggerFactory.getLogger(ShortUrlServiceImpl.class);

    @Autowired
    private ShortUrlMapper shortUrlMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public ServiceResult getShortUrlByLongUrl(ShortUrl shortUrl) {
        String longUrl = shortUrl.getLongUrl();
        String createdBy = shortUrl.getCreatedBy();
        String key = longUrl;
        if (!StringUtils.isEmpty(createdBy)) {
            key = key + ":" + createdBy;
        }
        if (StringUtils.isEmpty(longUrl)) {
            return ServiceResult.failed(10000, "长链接字符串为空");
        }
        String code = (String) redisTemplate.opsForHash().get(RedisKey.LONG_SHORT_HASH, key);
        if (!StringUtils.isEmpty(code)) {
            //返回缓存
            HashMap<String, String> map = new HashMap<>();
            map.put("longUrl", longUrl);
            map.put("code", code);
            return ServiceResult.ok(map);
        }
        ShortUrl shortUrlCreate = new ShortUrl();
        shortUrlCreate.setLongUrl(longUrl);

        Date expired = shortUrl.getExpired();
        if (expired != null && expired.after(new Date())) {
            shortUrlCreate.setExpired(expired);
        }
        Integer maxView = shortUrl.getMaxView();
        if (maxView != null && maxView > 0) {
            shortUrlCreate.setMaxView(maxView);
        }

        if (!StringUtils.isEmpty(createdBy)) {
            shortUrlCreate.setCreatedBy(createdBy);
        }

        shortUrlMapper.insertReturnId(shortUrlCreate);
        Long id = shortUrlCreate.getId();
        if (id != null) {
            code = ConvertRadix._10_to_N(id, 62);
            redisTemplate.opsForHash().put(RedisKey.LONG_SHORT_HASH, key, code);
            HashMap<String, String> map = new HashMap<>();
            map.put("longUrl", longUrl);
            map.put("code", code);
            return ServiceResult.ok(map);
        }
        return ServiceResult.failed(10001, "数据库插入失败");
    }

    @Override
    public ServiceResult getLongUrlByShortUrl(String shortUrlCode) {
        if (StringUtils.isEmpty(shortUrlCode)) {
            return ServiceResult.failed(10002, "短链接码为空");
        }
        long id = ConvertRadix.N_to_10(shortUrlCode, 62);
        ShortUrl shortUrl = shortUrlMapper.selectById(id);
        if (shortUrl == null) {
            return ServiceResult.failed(10003, "找不到该短链接");
        }
        if (shortUrl.getDelFlag() == 1) {
            return ServiceResult.failed(10007, "短链接已经被删除");
        }
        //计数
        redisTemplate.opsForHash().increment(RedisKey.SHORT_COUNT, String.valueOf(id), 1);
        HashMap<String, Object> map = new HashMap<>();
        map.put("longUrl", shortUrl.getLongUrl());
        map.put("code", shortUrlCode);
        map.put("id", shortUrl.getId());
        return ServiceResult.ok(map);
    }

    @Override
    public ServiceResult list(int page, int pageSize, Wrapper<ShortUrl> wrapper) {
        String userId = ThreadLocalUtils.USER_THREAD_LOCAL.get();
        if (StringUtils.isEmpty(userId)) {
            return ServiceResult.NO_LOGIN;
        }
        wrapper.andNew().eq("created_by", userId).and().eq("del_flag", 0);
        wrapper.orderBy("created_time", false);
        Page<ShortUrl> pageEntity = new Page<>();
        pageEntity.setSize(pageSize);
        pageEntity.setCurrent(page);
        pageEntity.setRecords(shortUrlMapper.selectPage(pageEntity, wrapper));
        Page<ShortUrlDTO> objectPage = new Page<>();
        try {
            $.bean.copyProperties(objectPage, pageEntity);
        } catch (InvocationTargetException | IllegalAccessException e) {
            logger.error("pageEntity转换出错", e);
        }
        List<ShortUrl> records = pageEntity.getRecords();
        List<ShortUrlDTO> list = records.stream().map(mapper -> {
            ShortUrlDTO shortUrlDTO = new ShortUrlDTO();
            try {
                //拷贝 ShortUrl 的对象数据到 ShortUrlDTO对象
                $.bean.copyProperties(shortUrlDTO, mapper);
                //转换10进制ID为62进制的短链接Code
                Long id = mapper.getId();
                String code = ConvertRadix._10_to_N(id, 62);
                shortUrlDTO.setCode(code);
                //清除短链接数字ID
                shortUrlDTO.setId(0L);
                // 将Redis中缓存的访问量写到实体类里
                String hget =
                        (String) redisTemplate.opsForHash().get(RedisKey.SHORT_COUNT, String.valueOf(id));
                int viewRedis = 0;
                if (StringUtils.hasLength(hget)) {
                    viewRedis = Integer.valueOf(hget);
                }
                Integer view = mapper.getView();
                shortUrlDTO.setView(view + viewRedis);
            } catch (InvocationTargetException | IllegalAccessException e) {
                logger.error("ShortUrl转换出错", e);
            }
            return shortUrlDTO;
        }).collect(Collectors.toList());
        objectPage.setRecords(list);
        return ServiceResult.ok(objectPage);
    }

    @Override
    public ServiceResult delete(String code) {
        //获取当前登录用户
        String userId = ThreadLocalUtils.USER_THREAD_LOCAL.get();
        if (StringUtils.isEmpty(userId)) {
            return ServiceResult.NO_LOGIN;
        }
        //将Code转换为10进制
        long id = ConvertRadix.N_to_10(code, 62);
        ShortUrl shortUrl = shortUrlMapper.selectById(id);
        if (shortUrl == null) {
            return ServiceResult.failed(10005, "找不到该短链接");
        }
        if (!userId.equals(shortUrl.getCreatedBy())) {
            return ServiceResult.failed(10006, "不是当前用户创建的短链接，没有删除权限");
        }

        //操作删除缓存中的链接
        String longUrl = shortUrl.getLongUrl();
        String createdBy = shortUrl.getCreatedBy();
        String key = longUrl;
        if (!StringUtils.isEmpty(createdBy)) {
            key = key + ":" + createdBy;
        }
        if (StringUtils.isEmpty(longUrl)) {
            return ServiceResult.failed(10000, "长链接字符串为空");
        }
        redisTemplate.opsForHash().delete(RedisKey.LONG_SHORT_HASH, key);
        //软删除，将delFlag置为1
        shortUrl.setDelFlag(1);
        shortUrlMapper.updateById(shortUrl);
        return ServiceResult.ok(null);
    }

    @Override
    public ServiceResult disabled(String code) {
        return null;
    }

    @Override
    public ServiceResult enabled(String code) {
        return null;
    }
}
